home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir31 / gusutils.zip / GUS.PAS < prev    next >
Pascal/Delphi Source File  |  1994-02-08  |  21KB  |  1,021 lines

  1. (****************************************************************************)
  2. (* Module     : GUS.PAS                                                     *)
  3. (* Verion     : 0.6ß                                                        *)
  4. (* Date       : Thu Feb 3, 1994                                             *)
  5. (* Pascal     : TP 7.0                                                      *)
  6. (****************************************************************************)
  7. (*                                                                          *)
  8. (* NOTICE OF COPYRIGHT AND OWNERSHIP OF SOFTWARE:                           *)
  9. (*                                                                          *)
  10. (* Copyright (C) 1993, 1994 by MESS Computer Services.                      *)
  11. (* Portions Copyright (C) 1993, 1994 by TBP Electronics Ltd.                *)
  12. (* All rights reserved.                                                     *)
  13. (*                                                                          *)
  14. (****************************************************************************)
  15. (* MESS Computer Services V.O.F.        MM   MM  EEEEEE   SSSSS   SSSSS     *)
  16. (* Jadestraat 54                        M M M M  E       S       S          *)
  17. (* 4817 JK  Breda                       M  M  M  EEEE     SSSS    SSSS      *)
  18. (* The Netherlands                      M     M  E            S       S     *)
  19. (*                                      M     M  EEEEEE  SSSSS   SSSSS      *)
  20. (* Tel: +31-76 22 34 31                                                     *)
  21. (* Fax: +31-76 20 46 23               Many Efforts for Structured Systems   *)
  22. (* Email: appel@stack.urc.tue.nl                                            *)
  23. (****************************************************************************)
  24.  
  25. {$A-,B-,D+,E-,F-,G+,I-,L+,N-,O-,P-,Q-,R-,S-,T-,V-,X+}
  26. {$M 1024,0,0}
  27.  
  28. unit GUS;
  29.  
  30. interface
  31.  
  32. (* PUBLIC *)
  33.  
  34. uses
  35.   Dos;
  36.  
  37. const
  38.   (* BALANCE *)
  39.   Left    = 0;
  40.   Middle  = 8;
  41.   Right   = 15;
  42.  
  43.   (* MODE *)
  44.   Bit8    = 0;
  45.   Bit16   = 4;
  46.   LoopOff = 0;
  47.   LoopOn  = 8;
  48.   UniDir  = 0;
  49.   BiDir   = 16;
  50.   Forw    = 0;
  51.   Backw   = 64;
  52.   Up      = 0;
  53.   Down    = 64;
  54.  
  55.   (* LOCATION *)
  56.   Current   = $8A;
  57.   LoopStart = $82;
  58.   LoopEnd   = $84;
  59.  
  60.   (* OUTPUT *)
  61.   LineIn    = -1;
  62.   LineOut   = -2;
  63.   MicIn     = 4;
  64.  
  65. var
  66.   GusBase        : Word;         (* GUS I/O BASE 2x0 *)
  67.   GusMemory      : Word;         (* GUS MEMORY SIZE 256K, 512K, 768K, 1024K *)
  68.   GusEnvironment : string[20];   (* GUS "ULTRASND" ENVIRONMENT STRING *)
  69.  
  70.   GusVoices      : Byte;         (* NUMBER OF ACTIVE VOICES *)
  71.   GusDataConvert : Boolean;      (* CONVERT DATA FOR GUSWRITE AND GUSREAD *)
  72.   GusData16Bits  : Boolean;      (* 16BITS DATA FOR GUSWRITE AND GUSREAD *)
  73.  
  74. function  GusFind : Boolean;
  75. function  MegaEm : Boolean;
  76. procedure GusInit (MaxVoices : Byte);
  77. procedure GusMixer (Output : ShortInt);
  78.  
  79. procedure GusPoke (Address : LongInt ; Value : Byte);
  80. function  GusPeek (Address : LongInt) : Byte;
  81. procedure GusWrite (Address : LongInt; var Buffer; Count : Word);
  82. procedure GusRead (Address : LongInt; var Buffer; Count : Word);
  83.  
  84. procedure VoiceInit (Voice : Byte);
  85.  
  86. procedure VoiceBalance (Voice : Byte; Balance : Byte);
  87. procedure VoiceVolume (Voice : Byte; Volume : Word);
  88. procedure VoiceFreq (Voice : Byte; Freq : Word);
  89. procedure VoiceStart (Voice : Byte);
  90. procedure VoiceStop (Voice : Byte);
  91. procedure VoiceMode (Voice : Byte; Mode : Byte);
  92. procedure VoiceSample (Voice : Byte; Start, LoopStart, LoopEnd : LongInt);
  93.  
  94. procedure RampStart (Voice : Byte);
  95. procedure RampStop (Voice : Byte);
  96. procedure RampMode (Voice : Byte; Mode : Byte);
  97. procedure RampRate (Voice : Byte; Scale, Rate : Byte);
  98. procedure RampRange (Voice : Byte; Lower, Upper : Word);
  99.  
  100. function GetVoiceLoc (Voice : Byte; Location : Byte) : LongInt;
  101. function VoiceActive (Voice : Byte) : Boolean;
  102.  
  103. (* PRIVATE *)
  104.  
  105. const
  106.   (* OUTPUT *)
  107.   Disabled  = 8 + 2 + 1;
  108.  
  109.   (* FREQUENCY *)
  110.   FREQ_DIV_TABLE : array [0..31] of Word =
  111.                    ($250, $128, $0C5, $094, $076, $063, $055, $04A,
  112.                     $042, $03C, $036, $032, $02E, $02B, $028, $025,
  113.                     $023, $021, $01F, $01E, $01C, $01B, $01A, $019,
  114.                     $018, $017, $016, $015, $014, $014, $013, $012);
  115.  
  116. var
  117.   (* GUS DATA *)
  118.   GusDataHigh         : Byte;      (* HIGH PART OF THE 16BITS GUS DATA *)
  119.  
  120.   (* VARIABLES *)
  121.   GF1_ACTIVE_VOICE    : Byte;
  122.   GF1_FREQ_DIV        : Word;
  123.  
  124.   (* I/O MAP *)
  125.   MIX_CONTROL_REG     : Word;
  126.   IRQ_STATUS_REG      : Word;
  127.   TIMER_CONTROL_REG   : Word;
  128.   TIMER_DATA          : Word;
  129.   IRQ_DMA_CONTROL_REG : Word;
  130.   GF1_PAGE_REG        : Word;
  131.   GF1_REG_SELECT      : Word;
  132.   DRAM                : Word;
  133.  
  134. procedure GF1_DELAY;
  135.  
  136. procedure GF1_OUT_BYTE;
  137. procedure GF1_OUT_WORD;
  138. procedure GF1_OUT_ADDR;
  139.  
  140. function GF1_IN_BYTE : Byte;
  141. function GF1_IN_WORD : Word;
  142. function GF1_IN_ADDR : LongInt;
  143.  
  144. procedure GF1_VOICE;
  145. procedure GF1_VOICE_CONTROL;
  146. procedure GF1_RAMP_CONTROL;
  147.  
  148. implementation
  149.  
  150. procedure GF1_DELAY; assembler;
  151. asm
  152.   push    ax
  153.   push  dx
  154.   mov   ah, 80
  155.  
  156.   @lab1:
  157.   mov    dx, DRAM
  158.   in    al, dx
  159.   dec   ah
  160.   jnz   @lab1
  161.  
  162.   pop   dx
  163.   pop    ax
  164. end;
  165.  
  166. procedure GF1_OUT_BYTE; assembler;
  167. (*
  168.    INPUT: AL -> GF1_REGISTER_SELECT
  169.           BL -> GF1_DATA
  170. *)
  171. asm
  172.   mov   dx, GF1_REG_SELECT
  173.   out   dx, al
  174.   inc   dx
  175.   inc   dx
  176.   mov   al, bl
  177.   out   dx, al
  178. end;
  179.  
  180. procedure GF1_OUT_WORD; assembler;
  181. (*
  182.    INPUT  : AL -> GF1_REGISTER_SELECT
  183.             BX -> GF1_DATA
  184. *)
  185. asm
  186.   mov   dx, GF1_REG_SELECT
  187.   out   dx, al
  188.   inc   dx
  189.   mov   ax, bx
  190.   out   dx, ax
  191. end;
  192.  
  193. procedure GF1_OUT_ADDR; assembler;
  194. (*
  195.    INPUT  : AL(+1) -> GF1_REGISTER_SELECT
  196.             BX:SI  -> GF1_DATA
  197. *)
  198. asm
  199.   mov   dx, GF1_REG_SELECT
  200.   out   dx, al
  201.   mov   cl, al
  202.   inc   dx
  203.   mov   ax, si
  204.   shr   ax, 7
  205.   ror   bx, 7
  206.   or    ax, bx
  207.   out   dx, ax
  208.   dec   dx
  209.   mov   al, cl
  210.   inc   al
  211.   out   dx, al
  212.   inc   dx
  213.   mov   ax, si
  214.   shl   ax, 9
  215.   out   dx, ax
  216. end;
  217.  
  218. function GF1_IN_BYTE : Byte; assembler;
  219. (*
  220.    INPUT  : AL -> GF1_REGISTER_SELECT
  221.    OUTPUT : AL <- GF1_DATA
  222. *)
  223. asm
  224.   mov   dx, GF1_REG_SELECT
  225.   out   dx, al
  226.   inc   dx
  227.   inc   dx
  228.   in    al, dx
  229. end;
  230.  
  231. function GF1_IN_WORD : Word; assembler;
  232. (*
  233.    INPUT  : AL -> GF1_REGISTER_SELECT
  234.    OUTPUT : AX <- GF1_DATA
  235. *)
  236. asm
  237.   mov   dx, GF1_REG_SELECT
  238.   out   dx, al
  239.   inc   dx
  240.   in    ax, dx
  241. end;
  242.  
  243. function GF1_IN_ADDR : LongInt; assembler;
  244. (*
  245.    INPUT  : AL(+1) -> GF1_REGISTER_SELECT
  246.    OUTPUT : AX:DX  <- GF1_DATA
  247. *)
  248. asm
  249.   mov   dx, GF1_REG_SELECT
  250.   out   dx, al
  251.   mov   cl, al
  252.   inc   dx
  253.   in    ax, dx
  254.   mov   di, ax
  255.   shr   di, 9
  256.   and   di, 15
  257.   mov   si, ax
  258.   shl   si, 7
  259.   dec   dx
  260.   mov   al, cl
  261.   inc   al
  262.   out   dx, al
  263.   inc   dx
  264.   in    ax, dx
  265.   shr   ax, 9
  266.   or    ax, si
  267.   mov   dx, di
  268. end;
  269.  
  270. procedure GF1_VOICE; assembler;
  271. (*
  272.    INPUT: AL -> GF1_PAGE_REG
  273. *)
  274. asm
  275.   cmp   GF1_ACTIVE_VOICE, al
  276.   je    @lab1
  277.   mov   GF1_ACTIVE_VOICE, al
  278.  
  279.   mov   dx, GF1_PAGE_REG
  280.   out   dx, al
  281.   @lab1:
  282. end;
  283.  
  284. procedure GF1_VOICE_CONTROL; assembler;
  285. (*
  286.    INPUT: BL -> VOICE CONTROL REGISTER (AND)
  287.           BH -> VOICE CONTROL REGISTER (OR)
  288. *)
  289. asm
  290.   mov   al, 80h
  291.   call  GF1_IN_BYTE
  292.  
  293.   and   bl, al
  294.   or    bl, bh
  295.   xor   al, al
  296.   call  GF1_OUT_BYTE
  297. end;
  298.  
  299. procedure GF1_RAMP_CONTROL; assembler;
  300. (*
  301.    INPUT: BL -> VOICE CONTROL REGISTER (AND)
  302.           BH -> VOICE CONTROL REGISTER (OR)
  303. *)
  304. asm
  305.   mov   al, 8Dh
  306.   call  GF1_IN_BYTE
  307.  
  308.   and   bl, al
  309.   or    bl, bh
  310.   mov   al, 0Dh
  311.   call  GF1_OUT_BYTE
  312. end;
  313.  
  314. function GusMemSize : Word; assembler;
  315. asm
  316.   (* SIZE := 1024 *)
  317.   mov   cx, 1024
  318.  
  319.   @lab1:
  320.   (* ADDRESS LOW  := FFFFh *)
  321.   mov   al, 43h
  322.   mov   bx, 0FFFFh
  323.   call  GF1_OUT_WORD
  324.  
  325.   (* ADDRESS HIGH := SIZE SHR 6 - 1 *)
  326.   mov   al, 44h
  327.   mov   bx, cx
  328.   shr   bx, 6
  329.   dec   bx
  330.   call  GF1_OUT_WORD
  331.  
  332.   (* TEST MEMORY *)
  333.   mov   dx, DRAM
  334.   in    al, dx
  335.   mov   bl, al
  336.   xor   al, 0FFh
  337.   out   dx, al
  338.   call  GF1_DELAY
  339.   in    al, dx
  340.   xor   al, 0FFh
  341.   out   dx, al
  342.   cmp   bl, al
  343.   je    @lab2
  344.   (* SIZE := SIZE - 256 *)
  345.   sub   cx, 256
  346.   jnz   @lab1
  347.   jmp   @lab3
  348.  
  349.   @lab2:
  350.   (* TEST GUS *)
  351.   mov   dx, GF1_REG_SELECT
  352.   inc   dx
  353.   in    al, dx
  354.   cmp   al, 0FFh
  355.   je    @lab3
  356.   inc   dx
  357.   in    al, dx
  358.   cmp   al, 0FFh
  359.   jne   @lab4
  360.  
  361.   @lab3:
  362.   (* MEM OR GUS NOT O.K. -> SIZE := 0 *)
  363.   xor   cx, cx
  364.  
  365.   @lab4:
  366.   (* GUSMEMSIZE := SIZE *)
  367.   mov   ax, cx
  368. end;
  369.  
  370. function GusNrOfVoices : Byte; assembler;
  371. asm
  372.   (* NR OF VOICES *)
  373.   mov   al, 8Eh
  374.   call  GF1_IN_BYTE
  375.   and   al, 31
  376. end;
  377.  
  378. (* PUBLIC *)
  379.  
  380. function GusFind : Boolean;
  381. var
  382.   Code : Integer;
  383. begin
  384.   GusEnvironment := GetEnv ('ULTRASND');
  385.  
  386.   if (GusEnvironment <> '') then
  387.   begin
  388.     Val ('$' + Copy (GusEnvironment, 1, 3), GusBase, Code);
  389.     if (Code <> 0) or (GusBase < $210) or
  390.        (GusBase > $2A0) or (GusBase and $F <> 0) then GusBase := $200
  391.   end
  392.     else GusBase := $200;
  393.  
  394.   Dec (GusBase, $10);
  395.  
  396.   repeat
  397.     (* GUSBASE *)
  398.     Inc (GusBase, $10);
  399.  
  400.     (* INTERNAL *)
  401.     asm
  402.       push   ax
  403.       (* 2x? *)
  404.       mov    ax, GusBase
  405.       mov    MIX_CONTROL_REG, ax
  406.       add    ax, 6h
  407.       mov    IRQ_STATUS_REG, ax
  408.       inc    ax
  409.       inc    ax
  410.       mov    TIMER_CONTROL_REG, ax
  411.       inc    ax
  412.       mov    TIMER_DATA, ax
  413.       inc    ax
  414.       inc    ax
  415.       mov    IRQ_DMA_CONTROL_REG, ax
  416.       (* 3x? *)
  417.       mov    ax, GusBase
  418.       add    ax, 102h
  419.       mov    GF1_PAGE_REG, ax
  420.       inc    ax
  421.       mov    GF1_REG_SELECT, ax
  422.       add    ax, 4h
  423.       mov    DRAM, ax
  424.       pop    ax
  425.     end;
  426.  
  427.     (* MEMORY *)
  428.     GusMemory := GusMemSize;
  429.   until (GusMemory <> 0) or (GusBase = $2A0);
  430.  
  431.   if (GusMemory = 0) then
  432.   begin
  433.     GusBase := 0;
  434.     GusFind := False;
  435.   end
  436.     else GusFind := True;
  437. end;
  438.  
  439. function MegaEm : Boolean; assembler;
  440. asm
  441.   (* CHECK INT 21H FOR MEGA-EM *)
  442.   mov   ax, 0FD12h
  443.   mov   bx, 3457h
  444.   int   21h
  445.   cmp   ax, 5678h
  446.   jne   @NoMegaEm
  447.   cmp   bx, 1235h
  448.   jne   @NoMegaEm
  449.   mov   ax, True
  450.   jmp   @lab1
  451.  
  452.   @NoMegaEm:
  453.   xor   ax, ax
  454.   @lab1:
  455. end;
  456.  
  457. procedure GusInit (MaxVoices : Byte); assembler;
  458. asm
  459.   (* RESET REG *)
  460.   mov    al, 4Ch
  461.   xor    bl, bl
  462.   call  GF1_OUT_BYTE
  463.   call    GF1_DELAY
  464.  
  465.   (* RESET REG *)
  466.   mov    al, 4Ch
  467.   mov    bl, 1h
  468.   call  GF1_OUT_BYTE
  469.   call    GF1_DELAY
  470.  
  471.   (* DRAM DMA CONTROL REG *)
  472.   mov    al, 41h
  473.   xor    bl, bl
  474.   call  GF1_OUT_BYTE
  475.   call    GF1_DELAY
  476.  
  477.   (* TIMER CONTROL *)
  478.   mov    al, 45h
  479.   xor    bl, bl
  480.   call  GF1_OUT_BYTE
  481.   call    GF1_DELAY
  482.  
  483.   (* SAMPLING CONTROL REG *)
  484.   mov    al, 49h
  485.   xor    bl, bl
  486.   call  GF1_OUT_BYTE
  487.   call    GF1_DELAY
  488.  
  489.   (* ACTIVE VOICES *)
  490.   mov    bl, MaxVoices
  491.   mov   GusVoices, bl
  492.   dec   bl
  493.   mov    si, bx
  494.   and    si, 0FFh
  495.   shl    si, 1
  496.   mov    ax, [offset FREQ_DIV_TABLE + si]
  497.   mov    GF1_FREQ_DIV, ax
  498.   or    bl, 0C0h
  499.   mov   al, 0Eh
  500.   call  GF1_OUT_BYTE
  501.   call    GF1_DELAY
  502.  
  503.   xor   cx, cx
  504.   @lab1:
  505.   (* VOICE *)
  506.   mov   al, cl
  507.   call  GF1_VOICE
  508.   call    GF1_DELAY
  509.  
  510.   (* VOICE CONTROL *)
  511.   xor   al, al
  512.   mov   bl, 3h
  513.   call  GF1_OUT_BYTE
  514.  
  515.   (* VOLUME CONTROL *)
  516.   mov   al, 0Dh
  517.   mov   bl, 3h
  518.   call  GF1_OUT_BYTE
  519.  
  520.   (* FREQUENCY = 0  (BX) *)
  521.   xor   bx, bx
  522.   mov   al, 1h
  523.   call  GF1_OUT_WORD
  524.  
  525.   (* STARTING ADDRESS = 0 (BX) *)
  526.   mov   al, 2h
  527.   call  GF1_OUT_WORD
  528.   mov   al, 3h
  529.   call  GF1_OUT_WORD
  530.  
  531.   (* END ADDRESS = 0 (BX) *)
  532.   mov   al, 4h
  533.   call  GF1_OUT_WORD
  534.   mov   al, 5h
  535.   call  GF1_OUT_WORD
  536.  
  537.   (* VOLUME RAMP START = 0 (BL) *)
  538.   mov   al, 7h
  539.   call  GF1_OUT_BYTE
  540.  
  541.   (* VOLUME RAMP END = 0 (BL) *)
  542.   mov   al, 8h
  543.   call  GF1_OUT_BYTE
  544.  
  545.   (* CURRENT VOLUME = 0 (BX) *)
  546.   mov   al, 9h
  547.   call  GF1_OUT_WORD
  548.  
  549.   (* CURRENT ADDRESS = 0 (BX) *)
  550.   mov   al, 0Ah
  551.   call  GF1_OUT_WORD
  552.   mov   al, 0Bh
  553.   call  GF1_OUT_WORD
  554.  
  555.   (* VOLUME RAMP RATE = 0 (BL) *)
  556.   mov   al, 6h
  557.   call  GF1_OUT_BYTE
  558.  
  559.   (* PAN POSITION *)
  560.   mov   al, 0Ch
  561.   mov   bl, Middle
  562.   call  GF1_OUT_BYTE
  563.  
  564.   inc   cx
  565.   cmp   cx, 20h
  566.   jne   @lab1
  567.  
  568.   (* RESET REG *)
  569.   mov    al, 4Ch
  570.   mov    bl, 7h
  571.   call  GF1_OUT_BYTE
  572.   call    GF1_DELAY
  573. end;
  574.  
  575. procedure GusMixer (Output : ShortInt); assembler;
  576. asm
  577.   mov   dx, MIX_CONTROL_REG
  578.   mov   al, Disabled
  579.   xor   al, 80
  580.   add   al, Output
  581.   xor   al, 80
  582.   out   dx, al
  583. end;
  584.  
  585. procedure GusPoke (Address : LongInt; Value : Byte); assembler;
  586. asm
  587.   (* ADDRESS LOW *)
  588.   mov   al, 43h
  589.   mov   bx, [bp + offset Address + 0]
  590.   call  GF1_OUT_WORD
  591.  
  592.   (* ADDRESS HIGH *)
  593.   mov   al, 44h
  594.   mov   bl, [bp + offset Address + 2]
  595.   call  GF1_OUT_BYTE
  596.  
  597.   (* WRITE DRAM *)
  598.   mov   dx, DRAM
  599.   mov   al, Value
  600.   out   dx, al
  601. end;
  602.  
  603. function GusPeek (Address : LongInt) : Byte; assembler;
  604. asm
  605.   (* ADDRESS LOW *)
  606.   mov   al, 43h
  607.   mov   bx, [bp + offset Address + 0]
  608.   call  GF1_OUT_WORD
  609.  
  610.   (* ADDRESS HIGH *)
  611.   mov   al, 44h
  612.   mov   bl, [bp + offset Address + 2]
  613.   call  GF1_OUT_BYTE
  614.  
  615.   (* READ DRAM *)
  616.   mov   dx, DRAM
  617.   in    al, dx
  618. end;
  619.  
  620. procedure GusWrite (Address : LongInt; var Buffer; Count : Word); assembler;
  621. asm
  622.   (* PUSH ES *)
  623.   push  es
  624.  
  625.   (* TEST COUNT *)
  626.   cmp   Count, 0
  627.   je    @stop
  628.  
  629.   (* SET REGISTERS  CX:SI=ADDRESS  ES:DI=BUFFER *)
  630.   mov   si, [bp + offset Address + 0]
  631.   mov   cx, [bp + offset Address + 2]
  632.  
  633.   mov   di, [bp + offset Buffer + 0]
  634.   mov   es, [bp + offset Buffer + 2]
  635.  
  636.   (* GUSDATAHIGH := FALSE *)
  637.   mov   GusDataHigh, 1
  638.  
  639.   (* ADDRESS HIGH *)
  640.   mov   al, 44h
  641.   mov   bl, cl
  642.   call  GF1_OUT_BYTE
  643.   (* SELECT ADDRESS LOW *)
  644.   mov   dx, GF1_REG_SELECT
  645.   mov   al, 43h
  646.   out   dx, al
  647.  
  648.   @lab1:
  649.   (* ADDRESS LOW *)
  650.   mov   dx, GF1_REG_SELECT
  651.   inc   dx
  652.   mov   ax, si
  653.   out   dx, ax
  654.  
  655.   (* READ BUFFER *)
  656.   mov   al, es:[di]
  657.   inc   di
  658.  
  659.   (* 2CMP / 16BITS *)
  660.   cmp   GusDataConvert, 0
  661.   je    @signed
  662.   cmp   GusData16Bits, 0
  663.   je    @unsigned
  664.   dec   GusDataHigh
  665.   jnz   @unsigned
  666.   mov   GusDataHigh, 2
  667.   jmp   @signed
  668.   @unsigned:
  669.   xor   al, 80h
  670.  
  671.   @signed:
  672.   (* WRITE DRAM *)
  673.   mov   dx, DRAM
  674.   out   dx, al
  675.  
  676.   (* INC ADDRESS *)
  677.   inc   si
  678.   jnz   @lab2
  679.   inc   cx
  680.  
  681.   (* ADDRESS HIGH *)
  682.   mov   al, 44h
  683.   mov   bl, cl
  684.   call  GF1_OUT_BYTE
  685.   (* SELECT ADDRESS LOW *)
  686.   mov   dx, GF1_REG_SELECT
  687.   mov   al, 43h
  688.   out   dx, al
  689.  
  690.   @lab2:
  691.   (* LOOP UNTIL COUNT = 0 *)
  692.   dec   Count
  693.   jnz   @lab1
  694.  
  695.   @stop:
  696.   (* POP ES *)
  697.   pop   es
  698. end;
  699.  
  700. procedure GusRead (Address : LongInt; var Buffer; Count : Word); assembler;
  701. asm
  702.   (* PUSH ES *)
  703.   push  es
  704.  
  705.   (* TEST COUNT *)
  706.   cmp   Count, 0
  707.   je    @stop
  708.  
  709.   (* SET REGISTERS  CX:SI=ADDRESS  ES:DI=BUFFER *)
  710.   mov   si, [bp + offset Address + 0]
  711.   mov   cx, [bp + offset Address + 2]
  712.  
  713.   mov   di, [bp + offset Buffer + 0]
  714.   mov   es, [bp + offset Buffer + 2]
  715.  
  716.   (* CLD *)
  717.   cld
  718.  
  719.   (* GUSDATAHIGH := FALSE *)
  720.   mov   GusDataHigh, 1
  721.  
  722.   (* ADDRESS HIGH *)
  723.   mov   al, 44h
  724.   mov   bl, cl
  725.   call  GF1_OUT_BYTE
  726.   (* SELECT ADDRESS LOW *)
  727.   mov   dx, GF1_REG_SELECT
  728.   mov   al, 43h
  729.   out   dx, al
  730.  
  731.   @lab1:
  732.   (* ADDRESS LOW *)
  733.   mov   dx, GF1_REG_SELECT
  734.   inc   dx
  735.   mov   ax, si
  736.   out   dx, ax
  737.  
  738.   (* READ DRAM *)
  739.   mov   dx, DRAM
  740.   in    al, dx
  741.  
  742.   (* 2CMP / 16BITS *)
  743.   cmp   GusDataConvert, 0
  744.   je    @signed
  745.   cmp   GusData16Bits, 0
  746.   je    @unsigned
  747.   dec   GusDataHigh
  748.   jnz   @unsigned
  749.   mov   GusDataHigh, 2
  750.   jmp   @signed
  751.   @unsigned:
  752.   xor   al, 80h
  753.  
  754.   @signed:
  755.   (* WRITE BUFFER *)
  756.   stosb
  757.  
  758.   (* INC ADDRESS *)
  759.   inc   si
  760.   jnz   @lab2
  761.   inc   cx
  762.  
  763.   (* ADDRESS HIGH *)
  764.   mov   al, 44h
  765.   mov   bl, cl
  766.   call  GF1_OUT_BYTE
  767.   (* SELECT ADDRESS LOW *)
  768.   mov   dx, GF1_REG_SELECT
  769.   mov   al, 43h
  770.   out   dx, al
  771.  
  772.   @lab2:
  773.   (* LOOP UNTIL COUNT = 0 *)
  774.   dec   Count
  775.   jnz   @lab1
  776.  
  777.   @stop:
  778.   (* POP ES *)
  779.   pop   es
  780. end;
  781.  
  782. procedure VoiceInit (Voice : Byte);
  783. begin
  784.   VoiceStop (Voice);
  785.   RampStop (Voice);
  786.  
  787.   RampMode (Voice, LoopOff+UniDir+Up);
  788.   RampRange (Voice, $000, $000);
  789.   RampRate (Voice, 0, 0);
  790.  
  791.   VoiceMode (Voice, Bit8 + LoopOff + UniDir + Forw);
  792.   VoiceFreq (Voice, 0);
  793.   VoiceBalance (Voice, Middle);
  794.   VoiceVolume (Voice, $000);
  795.   VoiceSample (Voice, 0, 0, 0);
  796. end;
  797.  
  798. procedure VoiceBalance (Voice : Byte; Balance : Byte); assembler;
  799. asm
  800.   (* VOICE *)
  801.   mov   al, Voice
  802.   call  GF1_VOICE
  803.  
  804.   (* PANNING *)
  805.   mov   al, 0Ch
  806.   mov   bl, Balance
  807.   call  GF1_OUT_BYTE
  808. end;
  809.  
  810. procedure VoiceVolume (Voice : Byte; Volume : Word); assembler;
  811. asm
  812.   (* VOICE *)
  813.   mov   al, Voice
  814.   call  GF1_VOICE
  815.  
  816.   (* VOLUME *)
  817.   mov   al, 9h
  818.   mov   bx, Volume
  819.   shl   bx, 4
  820.   call  GF1_OUT_WORD
  821. end;
  822.  
  823. procedure VoiceFreq (Voice : Byte; Freq : Word); assembler;
  824. asm
  825.   (* VOICE *)
  826.   mov   al, Voice
  827.   call  GF1_VOICE
  828.  
  829.   (* FREQUENCY *)
  830.   xor   dx, dx
  831.   mov   ax, Freq
  832.   div   GF1_FREQ_DIV
  833.   mov   bx, ax
  834.   mov   al, 1h
  835.   call  GF1_OUT_WORD
  836. end;
  837.  
  838. procedure VoiceStart (Voice : Byte); assembler;
  839. asm
  840.   (* VOICE *)
  841.   mov   al, Voice
  842.   call  GF1_VOICE
  843.  
  844.   (* VOICE CONTROL: START *)
  845.   mov   bl, 0FCh
  846.   xor   bh, bh
  847.   call  GF1_VOICE_CONTROL;
  848. end;
  849.  
  850. procedure VoiceStop (Voice : Byte); assembler;
  851. asm
  852.   (* VOICE *)
  853.   mov   al, Voice
  854.   call  GF1_VOICE
  855.  
  856.   (* VOICE CONTROL: STOP *)
  857.   mov   bl, 0FCh
  858.   mov   bh, 3h
  859.   call  GF1_VOICE_CONTROL;
  860. end;
  861.  
  862. procedure VoiceMode (Voice : Byte; Mode : Byte); assembler;
  863. asm
  864.   (* VOICE *)
  865.   mov   al, Voice
  866.   call  GF1_VOICE
  867.  
  868.   (* VOICE CONTROL: START *)
  869.   mov   bl, 83h
  870.   mov   bh, Mode
  871.   call  GF1_VOICE_CONTROL;
  872. end;
  873.  
  874. procedure VoiceSample (Voice : Byte; Start, LoopStart, LoopEnd : LongInt); assembler;
  875. asm
  876.   (* VOICE *)
  877.   mov   al, Voice
  878.   call  GF1_VOICE
  879.  
  880.   (* CURRENT LOCATION *)
  881.   mov   al, 0Ah
  882.   mov   si, [bp + offset Start + 0]
  883.   mov   bx, [bp + offset Start + 2]
  884.   call  GF1_OUT_ADDR
  885.  
  886.   (* LOOP START *)
  887.   mov   al, 2h
  888.   mov   si, [bp + offset LoopStart + 0]
  889.   mov   bx, [bp + offset LoopStart + 2]
  890.   call  GF1_OUT_ADDR
  891.  
  892.   (* LOOP END *)
  893.   mov   al, 4h
  894.   mov   si, [bp + offset LoopEnd + 0]
  895.   mov   bx, [bp + offset LoopEnd + 2]
  896.   call  GF1_OUT_ADDR
  897. end;
  898.  
  899. function GetVoiceLoc (Voice : Byte; Location : Byte) : LongInt; assembler;
  900. asm
  901.   (* VOICE *)
  902.   mov   al, Voice
  903.   call  GF1_VOICE
  904.  
  905.   (* ADDRESS LOCATION: 8Ah | 82h | 84h *)
  906.   mov   al, Location
  907.   call  GF1_IN_ADDR
  908. end;
  909.  
  910. function VoiceActive (Voice : Byte) : Boolean; assembler;
  911. asm
  912.   (* VOICE *)
  913.   mov   al, Voice
  914.   call  GF1_VOICE
  915.  
  916.   (* VOICE ACTIVE *)
  917.   mov   al, 80h
  918.   call  GF1_IN_BYTE
  919.   and   al, 3h  (* ?? bit 0 not allways set ?? *)
  920.   jz    @lab1
  921.   mov   al, 1h
  922.   @lab1:
  923.   xor   al, 1h
  924. end;
  925.  
  926. procedure  RampStart (Voice : Byte); assembler;
  927. asm
  928.   (* VOICE *)
  929.   mov   al, Voice
  930.   call  GF1_VOICE
  931.  
  932.   (* RAMP CONTROL: START *)
  933.   mov   bl, 0FCh
  934.   xor   bh, bh
  935.   call  GF1_RAMP_CONTROL;
  936. end;
  937.  
  938. procedure  RampStop (Voice : Byte); assembler;
  939. asm
  940.   (* VOICE *)
  941.   mov   al, Voice
  942.   call  GF1_VOICE
  943.  
  944.   (* RAMP CONTROL: STOP *)
  945.   mov   bl, 0FCh
  946.   mov   bh, 3
  947.   call  GF1_RAMP_CONTROL
  948. end;
  949.  
  950. procedure  RampMode (Voice : Byte; Mode : Byte); assembler;
  951. asm
  952.   (* VOICE *)
  953.   mov   al, Voice
  954.   call  GF1_VOICE
  955.  
  956.   (* RAMP CONTROL: MODE *)
  957.   mov   bl, 0A7h
  958.   mov   bh, Mode
  959.   call  GF1_RAMP_CONTROL
  960. end;
  961.  
  962. procedure  RampRate (Voice : Byte; Scale, Rate : Byte); assembler;
  963. asm
  964.   (* VOICE *)
  965.   mov   al, Voice
  966.   call  GF1_VOICE
  967.  
  968.   (* RAMP RATE *)
  969.   mov   al, 6h
  970.   mov   bl, Scale
  971.   shl   bl, 6
  972.   or    bl, Rate
  973.   call  GF1_OUT_BYTE
  974. end;
  975.  
  976. procedure  RampRange (Voice : Byte; Lower, Upper : Word); assembler;
  977. asm
  978.   (* VOICE *)
  979.   mov   al, Voice
  980.   call  GF1_VOICE
  981.  
  982.   (* RAMP RANGE *)
  983.   mov   al, 7h
  984.   mov   bx, Lower
  985.   shr   bx, 4
  986.   call  GF1_OUT_BYTE
  987.  
  988.   mov   al, 8h
  989.   mov   bx, Upper
  990.   shr   bx, 4
  991.   call  GF1_OUT_BYTE
  992. end;
  993.  
  994. begin
  995.   (* PUBLIC *)
  996.   GusFind;
  997.  
  998.   {
  999.   (* NO GUS OR MEGA-EM *)
  1000.   if (GusBase = 0) then
  1001.   begin
  1002.     WriteLn ('Gravis Ultrasound Unit                    V0.6');
  1003.     WriteLn ('(C)Copyright MESS Computer Services 1993, 1994');
  1004.     WriteLn;
  1005.     Write ('Error: ');
  1006.     if MegaEm
  1007.       then WriteLn ('Mega-Em is active.')
  1008.       else WriteLn ('No Ultrasound card found.');
  1009.     Halt (1);
  1010.   end;
  1011.   }
  1012.  
  1013.   GusVoices      := GusNrOfVoices + 1;
  1014.   GusDataConvert := False;
  1015.   GusData16Bits  := False;
  1016.  
  1017.   (* PRIVATE *)
  1018.   GF1_FREQ_DIV     := FREQ_DIV_TABLE [GusVoices - 1];
  1019.   GF1_ACTIVE_VOICE := $FF;
  1020. end.
  1021.